/* Gyroe 1.0.0 */
/* parser.c : Process statements, calling emit when
   necessary. Calls scanner to get tokens. */

#include "euphoria.h"
#include "main-.h"
#include "emit_calls.h"
#include "sym_fields.h"

int _15CreateTopLevel()
{
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _4TopLevelSub;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[TopLevelSub][S_NUM_ARGS] = 0
    Base[S_NUM_ARGS] = 0;

    // SymTab[TopLevelSub][S_TEMPS] = 0
    Base[S_TEMPS] = 0;

    // SymTab[TopLevelSub][S_CODE] = {}
    RefDS(_39);
    Base[S_CODE] = _39;

    // SymTab[TopLevelSub][S_FIRSTLINE] = 1
    Base[S_FIRSTLINE] = 1;
}

int _15EnterTopLevel()
{
    object_ptr Base;
    s1_ptr ptr;

    if (_4CurrentSub) {
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + _4CurrentSub;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        // SymTab[CurrentSub][S_CODE] = Code
        RefDS(_4Code);
        Base[S_CODE] = _4Code;
    }

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _4TopLevelSub;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // Code = SymTab[TopLevelSub][S_CODE]
    DeRef(_4Code);
    _4Code = Base[S_CODE];
    Ref(_4Code);

    _14previous_op = -1;
    _4CurrentSub = _4TopLevelSub;
}

int _15LeaveTopLevel()
{
    int _2, _3;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _4TopLevelSub;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    _11LastLineNumber = -1;

    // SymTab[TopLevelSub][S_CODE] = Code
    RefDS(_4Code);
    Base[S_CODE] = _4Code;

    // Code = {}
    RefDS(_39);
    DeRefDS(_4Code);
    _4Code = _39;

    _14previous_op = -1;
}

int _15InitParser()
{
    RefDS(_39);
    DeRefi(_15elist);
    _15elist = _39;

    RefDS(_39);
    DeRefi(_15exit_list);
    _15exit_list = _39;

    RefDS(_39);
    DeRefi(_15init_stack);
    _15init_stack = _39;

    _4CurrentSub = 0;
    _15CreateTopLevel();
    _15EnterTopLevel();

    DeRef(_15backed_up_tok);
    _15backed_up_tok = -999; // UNDEFINED

    _15loop_nest = 0;
    _15stmt_nest = 0;
}

int _15NotReached(int tok, int keyword)
{
    /* END, ELSE, ELSIF, END_OF_FILE */
    if (tok != 402 && tok != 23 && tok != 413 && tok != -21) {
        s1_ptr ptr;
        object_ptr Base;

        ptr = SEQ_PTR(_4file_name);
        Base = ptr->base;

        /* %s:%d - statement after %s will never be executed. */
        err_add(_10name_ext(Base[_4current_file_no]));
        err_add(NewString(":"));
        err_add(s1_from_int(_4line_number));
        err_add(NewString(" - statement after "));
        err_add(keyword);
        err_add(NewString(" will never be executed."));
        _6Warning(error_stack);

        RefDS(_39);
        error_stack = _39;        
    }
}

int _15InitCheck(int sym, int ref)
{
    int args, initlevel, mode, scope, obj;
    int varnum;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + sym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    mode = Base[S_MODE];
    scope = Base[S_SCOPE];

    // mode == M_NORMAL && scope != SC_LOOP_VAR && scope != SC_GLOOP_VAR
    if (mode == 1 && scope != 2 && scope != 4) {
        obj = Base[S_OBJ]; // SymTab[sym][S_OBJ]
        varnum = Base[S_VARNUM]; // SymTab[sym][S_VARNUM]
        initlevel = Base[S_INITLEVEL];

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + _4CurrentSub;
        ptr = SEQ_PTR(*Base);

        args = ptr->base[S_NUM_ARGS]; // SymTab[CurrentSub][S_NUM_ARGS]
        // scope != SC_PRIVATE && obj == NOVALUE || scope == SC_PRIVATE && varnum >= args
        if (scope != 3 && obj == _4NOVALUE || scope == 3 && varnum >= args) {
            if (initlevel == -1) {
                if (ref) {
                    if (scope == 6 || scope == 5) // SC_GLOBAL or SC_LOCAL
                        emit_m1(109); // GLOBAL_INIT_CHECK -- will become NOP2
                    else
                        emit_m1(30); // PRIVATE_INIT_CHECK
                    _14emit_addr(sym);
                }
                if (_15short_circuit <= 0 || _15short_circuit_B == 0) {
                    ptr = SEQ_PTR(_4SymTab);
                    Base = ptr->base + sym;
                    ptr = SEQ_PTR(*Base);
                    Base = ptr->base;
                    Append(&_15init_stack, _15init_stack, sym);
                    Base[S_INITLEVEL] = _15stmt_nest; // SymTab[sym][S_INITLEVEL]
                }
            }
        }
    }
}

int _15InitDelete()
{
    int i, j;
    object_ptr Base;
    s1_ptr ptr, ptr2;

    ptr2 = SEQ_PTR(_15init_stack);
    i = ptr2->length;
    j = 0; /* 0 so we get init_stack[$] */

    while (j < i) {
        Base = ptr2->base + ptr2->length - j;
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + *Base;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;
        j++;
        if (Base[S_INITLEVEL] > _15stmt_nest)
            Base[S_INITLEVEL] = -1;
        else
            break;
    }

    /* Slice the stack all at once. */
    if (j) {
        ptr = SEQ_PTR(_15init_stack);
        rhs_slice_target = (object_ptr)&_15init_stack;
        RHS_Slice((s1_ptr)_15init_stack, 1, ptr->length - j);
    }
}

int _15emit_forward_addr()
{
    int len;

    _14emit_addr(0);

    len = SEQ_PTR(_4Code)->length;
    Append(&_15branch_list, _15branch_list, len);
}

int _15StraightenBranches()
{
    int br0, i;
    object_ptr Base, Base0, target, br;
    s1_ptr ptr, ptr0;

    ptr = SEQ_PTR(_15branch_list);
    ptr0 = SEQ_PTR(_4Code);

    for (i = ptr->length;i > 0;i--) {
        // 	target = Code[branch_list[i]]
        Base = ptr->base + i; // branch_list[i]
        target = ptr0->base + *Base; // Code[branch_list[i]]

        // target <= length(Code)
        if (*target <= ptr0->length) {

            br = ptr0->base + *target; // Code[target]
            br0 = *br;

            // br == ELSE || br == ENDWHILE || br == EXIT then
            if (br0 == 23 || br0 == 22 || br0 == 61) {
                Base = ptr->base + i; // branch_list[i]
                Base0 = ptr0->base + *target + 1; // Code[target+1]
                _14backpatch(*Base, *Base0);
            }
        }
    }

    RefDS(_39);
    DeRefi(_15branch_list);
    _15branch_list = _39;
}

int _15AppendEList(int addr)
{
    Append(&_15elist, _15elist, addr);
}

int _15AppendXList(int addr)
{
    Append(&_15exit_list, _15exit_list, addr);
}

int _15PatchEList(int base)
{
    int clen, elist_top;
    object_ptr Base;
    s1_ptr ptr, ptr2;

    ptr = SEQ_PTR(_15elist);
    clen = SEQ_PTR(_4Code)->length + 1;
    elist_top = ptr->length;

    while (elist_top > base) {
        Base = ptr->base + elist_top;
        _14backpatch(*Base, clen);

        elist_top--;
    }

    rhs_slice_target = (object_ptr)&_15elist;
    RHS_Slice((s1_ptr)_15elist, 1, base);
}

int _15PatchXList(int base)
{
    int clen, exit_top;
    object_ptr Base;
    s1_ptr ptr, ptr2;

    ptr = SEQ_PTR(_15exit_list);
    clen = SEQ_PTR(_4Code)->length + 1;
    exit_top = ptr->length;

    while (exit_top > base) {
        Base = ptr->base + exit_top;
        _14backpatch(*Base, clen);

        exit_top--;
    }

    rhs_slice_target = (object_ptr)&_15exit_list;
    RHS_Slice((s1_ptr)_15exit_list, 1, base);
}

int _15putback(int t)
{
    _15backed_up_tok = t;
}

int _15next_token()
{
    int t;

    if (IS_ATOM(_15backed_up_tok)) {
        t = _11Scanner();
    }
    else {
        t = _15backed_up_tok;
        _15backed_up_tok = -999; // UNDEFINED
    }

    return t;
}

int _15Expr_list()
{
    int id, n, tok;
    s1_ptr ptr;

    tok = _15next_token();
    _15putback(tok);

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1); // tok[T_ID]

    if (id == -25) { // RIGHT_BRACE
        return 0;
    }
    else {
        n = 0;
        _15short_circuit--;

        while (1) {
            _15Expr();

            n++;
            tok = _15next_token();

            ptr = SEQ_PTR(tok);
            id = *(ptr->base + 1); // tok[T_ID]
            if (id != -30) // COMMA
                break;
        }
        _15short_circuit++;
    }

    _15putback(tok);

    return n;
}

int _15tok_match(int tok)
{
    int id, t;
    s1_ptr ptr;

    t = _15next_token();

    ptr = SEQ_PTR(t);
    id = *(ptr->base + 1); // t[T_ID]

    if (id != tok) {
        int actual, expected;
        int _3092;
        int _1, _2;

        expected = _14LexName(tok);
        id = *(ptr->base + 1);
        Ref(id);
        Ref(id);
        actual = _14LexName(id);

        err_add(NewString("Syntax error - expected to see possibly "));
        err_add(expected);
        err_add(NewString(" not "));
        err_add(actual);
        set_err_stack();
    }
}

int _15UndefinedVar(int s)
{
    int scope;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + s;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    scope = Base[S_SCOPE];

    if (scope == 9) { // SC_UNDEFINED
        /* %s has not been declared */
        err_add(Base[S_NAME]);
        err_add(" has not been declared.");
        set_err_stack();
    }
    else if (scope == 10) {
        /* Multiple definition error : %s is globally defined in\n
           ...(Display each file one at a time.) */
        err_add(NewString("Multiple definition error : "));
        err_add(Base[S_NAME]);
        err_add(" is globally defined in\n");

        ptr = SEQ_PTR(_10dup_globals);
        Base = ptr->base;

        int i, len;
        s1_ptr ptr2;
        object dup;
        object_ptr Base2;

        len = ptr->length;

        for (i = 1;i <= len;i++) {
            dup = ptr->base[i];

            err_add(NewString("    "));

            ptr2 = SEQ_PTR(_4SymTab);
            Base2 = ptr2->base + dup;
            ptr2 = SEQ_PTR(*Base2);
            Base2 = ptr2->base + S_FILE_NO;
            ptr2 = SEQ_PTR(_4file_name);
            Base2 = ptr2->base + *Base2;
            /* file_name[SymTab[dup][S_FILE_NO]] */

            err_add(*Base2);
            err_add(NewString("\n"));
        }
        set_err_stack();
    }
}

int _15WrongNumberArgs(int subsym, int only)
{
    int plural;
    int _3133 = 0;
    int _3126 = 0;
    int _1, _2;
    object_ptr Base, Base2;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + subsym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;
    _3126 = Base[S_NUM_ARGS];
    Ref(_3126);

    if (_3126 == 1) {
        // plural = ""
        RefDS(_39);
        plural = _39;
    }
    else {
        // plural = "s"
        RefDS(_3129);
        plural = _3129;
    }

    /* %s takes %s%d argument%s */

    err_add(Base[S_NAME]);
    err_add(NewString(" takes "));
    err_add(only);
    err_add(s1_from_int(Base[S_NUM_ARGS]));
    err_add(" argument");
    err_add(plural);
    set_err_stack();
}

int _15ParseArgs(int subsym)
{
    int id, n, tok;

    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + subsym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    n = Base[S_NUM_ARGS]; // SymTab[subsym][S_NUM_ARGS]
    _15short_circuit--;

    if (n) {
        int i = 1;
        for(;i < n;i++) {
                _15Expr();
                tok = _15next_token();

                ptr = SEQ_PTR(tok);
                id = *(ptr->base + 1);

                if (id != -30) { // COMMA
                    if (id == -27) { // RIGHT_ROUND
                       RefDS(_39);
                       _15WrongNumberArgs(subsym, _39);
                    }
                    else {
                        _15putback(tok);
                        _15tok_match(-30); // COMMA
                    }
                }
        }
        _15Expr();
    }
    tok = _15next_token();

    _15short_circuit++;

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    if (id != -27) { // RIGHT_ROUND
        if (id == -30) { // COMMA
            // WrongNumberArgs(subsym, "only ")
            RefDS(_3153);
            _15WrongNumberArgs(subsym, _3153);
        }
        else {
            _15putback(tok);
            _15tok_match(-27); // RIGHT_ROUND
        }
    }
}

int _15Factor()
{
    int id, n, tok, opcode;
    int save_factors, save_lhs_subs_level, scope, sym;
    int _3159, _3163;
    int _1, _2;
    int id0, id00;

    object_ptr Base;
    s1_ptr ptr;

    _15factors++;
    tok = _15next_token();

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);
    switch(id) {
        case -100:
        case 515:
            sym = *(ptr->base + 2);

            _15UndefinedVar(sym);

            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + sym;
            ptr = SEQ_PTR(*Base);
            Base = ptr->base; // SymTab[sym][S_USAGE]

            Base[S_USAGE] = 3; /* I believe this is U_READ */

            _15InitCheck(sym, 1); // TRUE
            _14emit_opnd(sym);

            if (sym == _15left_sym) {
               _15lhs_subs_level = 0; /* start counting subscripts */
            }

            _15short_circuit--;
            tok = _15next_token();

            Append(&_14current_sequence, _14current_sequence, sym);

            ptr = SEQ_PTR(tok);
            id00 = *(ptr->base + 1);
            while (id00 == -28) { // LEFT_SQUARE
                if (_15lhs_subs_level >= 0)
                    _15lhs_subs_level++;

                save_factors = _15factors;
                save_lhs_subs_level = _15lhs_subs_level;
                _15Expr();
                tok = _15next_token();

                ptr = SEQ_PTR(tok);
                id0 = *(ptr->base + 1);

                if (id0 == 516) { // SLICE
                    _15Expr();
                    emit_rhs_slice();
                    _15tok_match(-29); // RIGHT_SQUARE
                    tok = _15next_token();
                    break;
                }
                else {
                    _15putback(tok);
                    _15tok_match(-29); // RIGHT_SQUARE
                    _3163 = SEQ_PTR(_14current_sequence)->length - 1;
                    rhs_slice_target = (object_ptr)&_14current_sequence;
                    RHS_Slice((s1_ptr)_14current_sequence, 1, _3163);

                    emit_rhs_subs(); /* current_sequence will be updated */
                }
                _15factors = save_factors;
                _15lhs_subs_level = save_lhs_subs_level;
                tok = _15next_token();
                ptr = SEQ_PTR(tok);
                id00 = *(ptr->base + 1);
            }
            _3163 = SEQ_PTR(_14current_sequence)->length - 1;
            rhs_slice_target = (object_ptr)&_14current_sequence;
            RHS_Slice((s1_ptr)_14current_sequence, 1, _3163);
            _15putback(tok);
            _15short_circuit++;
            break;
        case -22: // DOLLAR
            _3163 = SEQ_PTR(_14current_sequence)->length;
            if (_3163)
                emit_dollar(); // DOLLAR
            else {
                // CompileErr("'$' must only appear between '[' and ']'")
                RefDS(_3188);
                _6CompileErr(_3188);
            }
            break;
        case 502: // ATOM
        case 503: // STRING
            _14emit_opnd(*(ptr->base + 2));
            break;
        case -24: // LEFT_BRACE
            n = _15Expr_list();
            _15tok_match(-25); // RIGHT_BRACE
            _14op_info1 = n;
            emit_right_brace_n(); // RIGHT_BRACE_N
            break;
        case -26: // LEFT_ROUND
            _15Expr();
            _15tok_match(-27); // RIGHT_ROUND
            break;
        case 501: // FUNC
        case 504: // TYPE
        case 524: // QUALIFIED_FUNC
        case 526: // QUALIFIED_TYPE
            sym = *(ptr->base + 2); // tok[T_SYM]

            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + sym;
            ptr = SEQ_PTR(*Base);
            Base = ptr->base;

            _15tok_match(-26); // LEFT_ROUND
            scope = Base[S_SCOPE]; // SymTab[sym][S_SCOPE]
            opcode = Base[S_OPCODE]; // SymTab[sym][S_OPCODE]
            _15ParseArgs(sym);

            /* Is the routine predefined? */
            if (scope == 7) { // SC_PREDEF
                _14emit_op(opcode);
            }
            else {
                _14op_info1 = sym;
                emit_proc(); // PROC
                if (_4OpTrace)
                    emit_m1(89); // UPDATE_GLOBALS
            }
            break;
        default:
            /* Syntax error - expected to see an expression, not %s */
            err_add(NewString("Syntax error - Expected to see an expression, not "));
            err_add(_14LexName(id));
            set_err_stack();
            break;
    }
}

int _15UFactor()
{
    int id, tok;
    s1_ptr ptr;

    tok = _15next_token();
    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    switch (id) {
        case 7: // NOT
            _15Factor();
            _14cont11ii(7, 1);
            _14previous_op = 7;
            break;
        case 10: // MINUS
            _15Factor();
            emit_uminus(); // UMINUS
            break;
        case 11: // PLUS
            _15Factor();
            break;
        default:
            _15putback(tok);
            _15Factor();
            break;
    }
}

int _15term()
/* Multiply and divide */
{
    int id, tok;
    s1_ptr ptr;

    _15UFactor();

    tok = _15next_token();
    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    // id == MULTIPLY || id == DIVIDE
    while (id == 13 || id == 14) {
        _15UFactor();
        if (id == 13) // MULTIPLY
            emit_multiply(); // MULTIPLY
        else
            emit_divide(); // DIVIDE

        tok = _15next_token();
        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
    }

    return tok;
}

int _15aexpr()
/* Plus and minus */
{
    int id, tok;
    s1_ptr ptr;

    tok = _15term();
    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    // id == PLUS or id == MINUS
    while (id == 11 || id == 10) {
        tok = _15term();
        if (id == 11) // PLUS
            emit_plus();
        else
            _14cont21ii(10, 0);

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
    }

    return tok;
}

int _15cexpr()
/* Concat expression
   X & Y */
{
    int concat_count = 0, id, tok;
    s1_ptr ptr;

    tok = _15aexpr();
    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    while (id == 15) { // CONCAT
        tok = _15aexpr();

        concat_count++;
        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
    }

    if (concat_count == 1) {
        _14cont21ii(15, 0); // CONCAT
    }
    /* We can't make this an else because
       concat_count could still be zero. */
    if (concat_count > 1){
        _14op_info1 = concat_count + 1;
        emit_concat_n(); // CONCAT_N
    }

    return tok;
}

int _15rexpr()
/* Relational expression
   <, >=, =, !=, <=, > */
{
    int id, tok;
    s1_ptr ptr;

    tok = _15cexpr();
    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    while (id <= 6 && id >= 1) { // id <= GREATER and id >= LESS
        tok = _15cexpr();
        _14cont21ii(id, 1); /* No emit_ for these */
        _14previous_op = id;

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
    }

    return tok;
}

int _15Expr()
{
    int id, patch = 0, tok;
    int tok_id;
    s1_ptr ptr;

    /* Process once before the loop, so the first run won't
       do unnecessary checks on id. */
    tok = _15rexpr();
    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    while (1) {
        // not OR && not AND && not XOR
        if (id != 9 && id != 8 && id != 154)
            break;

        // id != -1 && id != XOR && _15short_circuit > 0
        if (id != 154 && _15short_circuit > 0) {
            if (id == 9) // OR
                emit_sc1andor(145); // SC1_OR
            else
                emit_sc1andor(143); // SC1_AND
            patch = SEQ_PTR(_4Code)->length + 1;
            _15emit_forward_addr();
            _15short_circuit_B = 1;
        }

        tok = _15rexpr();

        if (id != 154 && _15short_circuit > 0) {
            ptr = SEQ_PTR(tok);
            tok_id = *(ptr->base + 1);
            if (tok_id != 409 && tok_id != 410) { // not THEN && not DO
                if (id == 9) // OR
                    emit_sc2andor(146); // SC2_OR
                else
                    emit_sc2andor(144); // SC2_OR
            }
            else {
                _15SC1_type = id; // if or while or elsif must patch.
                emit_sc2null();
            }
            _14backpatch(patch, SEQ_PTR(_4Code)->length + 1);
        }
        else {
            _14cont21ii(id, 1); /* cont21ii works for all (AND, OR, XOR) */
            _14previous_op = id;
        }

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
    }

    _15putback(tok);
    _15SC1_patch = patch; // extra line
}

int _15TypeCheck(int var)
{
    int which_type;
    int _3305;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + var;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    which_type = Base[S_VTYPE]; // SymTab[var][S_VTYPE]

    if (_4OpTypeCheck && which_type != _10object_type) {
    /* This was left with goto statements because GCC says that
       the stuff that which_type is checked against don't reduce
       to integers */
        /* Sometimes, a _CHECK may need to emit the var. */
        _14op_info1 = var;

        if (which_type == _10integer_type) {
            emit_integer_check();
            goto END;
        }

        if (which_type == _10sequence_type) {
            emit_sequence_check();
            goto END;
        }

        if (which_type == _10atom_type) {
            emit_atom_check(); // ATOM_CHECK
            goto END;
        }

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + which_type;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base + S_NEXT; // SymTab[which_type][S_NEXT]

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + *Base;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base + S_VTYPE; // SymTab[SymTab[which_type][S_NEXT]][S_VTYPE]
        if (*Base == _10integer_type) {
            emit_integer_check(); /* need integer conversion */
        }

        _14emit_opnd(var);
        _14op_info1 = which_type;
        emit_proc();
        emit_type_check();
    }

    if (_4OpTypeCheck == 0) {
        _14op_info1 = var;

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + which_type;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base + S_NEXT; // SymTab[which_type][S_NEXT]

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + *Base;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base + S_VTYPE; // SymTab[SymTab[which_type][S_NEXT]][S_VTYPE]

        if (which_type == _10sequence_type || *Base == _10sequence_type)
            emit_sequence_check();
        if (which_type == _10integer_type || *Base == _10integer_type)
            emit_integer_check();
    }
END:
    ;
}

int _15Assignment(int left_var)
{
    int assign_op, dangerous, id, slice, subs, subs1_patch;
    int tok;
    int _3359 = 0;
    int _1, _2, _3;
    int scope, mode;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(left_var);

    _15left_sym = *(ptr->base + 2); // left_var[T_SYM]
    _15UndefinedVar(_15left_sym);

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _15left_sym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    scope = Base[S_SCOPE]; // SymTab[left_sym][S_SCOPE]

    // SC_LOOP_VAR or SC_GLOOP_VAR
    if (scope == 2 || scope == 4) {
        RefDS(_3343);
        _6CompileErr(_3343); // "may not assign to a for-loop variable"
    }

    mode = Base[S_MODE]; // SymTab[left_sym][S_MODE]

    // M_CONSTANT
    if (mode == 2) {
        // 	CompileErr("may not change the value of a constant")
        RefDS(_3347);
        _6CompileErr(_3347); // "may not change the value of a constant"
    }

    //     SymTab[left_sym][S_USAGE] = or_bits(SymTab[left_sym][S_USAGE], U_WRITTEN)
    Base[S_USAGE] = Base[S_USAGE] | 2;

    tok = _15next_token();
    subs = 0;
    slice = 0; // FALSE
    dangerous = 0; // FALSE
    _14emit_opnd(_15left_sym);
    Append(&_14current_sequence, _14current_sequence, _15left_sym);

    while (1) {
        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1); // tok[T_ID]
        if (id != -28) // LEFT_SQUARE
            break;

        if (_14lhs_ptr) {
            ptr = SEQ_PTR(_14current_sequence);
            rhs_slice_target = (object_ptr)&_14current_sequence;
            RHS_Slice((s1_ptr)_14current_sequence, 1, ptr->length - 1);
            if (subs == 1) {
                subs1_patch = SEQ_PTR(_4Code)->length + 1;
                emit_lhs_subs(163); /* creates new current_sequence */
            }
            else {
                emit_lhs_subs(95); /* adds to current_sequence */
            }
        }
        subs++;

        if (subs == 1)
            _15InitCheck(_15left_sym, 1); // TRUE

        _15Expr();
        tok = _15next_token();

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1); // tok[T_ID]
        if (id == 516) { // SLICE
            _15Expr();
            slice = 1; // TRUE
            _15tok_match(-29); // RIGHT_SQUARE
            tok = _15next_token();

            break; /* no further subs or slices allowed */
        }
        else {
            _15putback(tok);

            _15tok_match(-29); // RIGHT_SQUARE
        }
        tok = _15next_token();
        _14lhs_ptr = 1; // TRUE
    }

    _14lhs_ptr = 0; // FALSE

    ptr = SEQ_PTR(tok);
    assign_op = *(ptr->base + 1); // tok[T_ID]

    /* EQUALS is three, PLUS_EQUALS is 518, and CONCAT_EQUALS is 522. The other _EQUALS ops
       have numbers falling between 518 and 522 */
    if (assign_op != 3 && assign_op < 518 && assign_op > 522) {
        RefDS(_3388);
        _6CompileErr(_3388); /* "Syntax error - expected to see =, +=, -=, *=, /= or &=" */
    }

    if (subs == 0) {
        if (assign_op == 3) { // EQUALS
            _15Expr(); /* RHS expression */
            _15InitCheck(_15left_sym, 0); // FALSE
        }
        else {
            _15InitCheck(_15left_sym, 1); // TRUE

            // 	    SymTab[left_sym][S_USAGE] = or_bits(SymTab[left_sym][S_USAGE], U_READ)
            _2 = (int)SEQ_PTR(_4SymTab);
            _3 = (int)(_15left_sym + ((s1_ptr)_2)->base);
            DeRef(_3359);
            _2 = (int)SEQ_PTR(_4SymTab);
            _3359 = *(((s1_ptr)_2)->base + _15left_sym);
            RefDS(_3359);
            _2 = (int)SEQ_PTR(_3359);
            _3359 = *(((s1_ptr)_2)->base + S_USAGE);
            Ref(_3359);
            if (IS_ATOM_INT(_3359)) {
                _3359 = (_3359 | 1);
            }
            else {
                _3359 = binary_op(OR_BITS, _3359, 1);
            }
            Ref(_3359);
            _2 = (int)SEQ_PTR(*(int *)_3);
            _2 = (int)(((s1_ptr)_2)->base + S_USAGE);
            *(int *)_2 = _3359;
            _14emit_opnd(_15left_sym);

            _15Expr(); /* RHS expression */
            _14emit_assign_op(assign_op);
        }

        emit_assign(); // ASSIGN
        _15TypeCheck(_15left_sym);
    }
    else {
        _15factors = 0;
        _15lhs_subs_level = -1;

        /* RHS expression */
        _15Expr();

        if (subs > 1) {
            if (_15factors == 1 && _15lhs_subs_level >= 0 && _15lhs_subs_level < subs+slice)
                dangerous = 1;

            if (dangerous)
                _14backpatch(subs1_patch, 168);
        }

        if (slice) {
            if (assign_op != 3) { // EQUALS
                if (subs == 1)
                    emit_assign_op_slice(152); // ASSIGN_OP_SLICE
                else
                    emit_assign_op_slice(167); // PASSIGN_OP_SLICE
               _14emit_assign_op(assign_op);
            }
            if (subs == 1)
               emit_assign_slice(45); // ASSIGN_SLICE
            else
               emit_assign_slice(165); // PASSIGN_SLICE
        }
        else {
            if (assign_op == 3) { // EQUALS
                if (subs == 1)
                    emit_assign_subs();
                else
                    emit_m3(164); // PASSIGN_SUBS
            }
            else {
                if (subs == 1)
                    emit_opsubs(151); // ASSIGN_OP_SUBS
                else
                    emit_opsubs(166); // PASSIGN_OP_SUBS
                _14emit_assign_op(assign_op);
                if (subs == 1)
                    emit_assign_subs2();
                else
                    emit_m3(164); // PASSIGN_SUBS
            }
        }

        if (subs > 1) {
            if (dangerous) {
                _14Push(_15left_sym);
                _14Push(_14lhs_subs1_copy_temp); /* will be freed */
                _14previous_op = -1;
                emit_assign();
            }
            else {
                _14TempFree(_14lhs_subs1_copy_temp);
            }
        }

        // OpTypeCheck and SymTab[left_sym][S_VTYPE] != sequence_type then
        if (_4OpTypeCheck) {
            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + _15left_sym;
            ptr = SEQ_PTR(*Base);
            Base = ptr->base + S_VTYPE; // SymTab[left_sym][S_VTYPE]
            if (*Base != _10sequence_type)
                _15TypeCheck(_15left_sym);
        }
    }

    ptr = SEQ_PTR(_14current_sequence);
    rhs_slice_target = (object_ptr)&_14current_sequence;
    RHS_Slice((s1_ptr)_14current_sequence, 1, ptr->length - 1);

    if (_4OpTrace) {
        emit_m1(87); // DISPLAY_VAR
        _14emit_addr(_15left_sym);
    }

    DeRef(_3359);
}

int _15Return_statement()
{
    int tok, id;
    object_ptr Base;
    s1_ptr ptr;

    if (_4CurrentSub == _4TopLevelSub) {
        // CompileErr("return must be inside a procedure or function")
        RefDS(_3427);
        _6CompileErr(_3427);
    }

    if (_4OpTrace) {
        emit_m1(88); // ERASE_PRIVATE_NAMES
        _14emit_addr(_4CurrentSub);
    }

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _4CurrentSub;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base + S_TOKEN;

    if (*Base != 27) {
        _15Expr();
        _15FuncReturn = 1;
        emit_returnf();
    }
    else {
        emit_returnp();
    }

    tok = _15next_token();
    _15putback(tok);

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);
    RefDS(_670);
    _15NotReached(id, _670);
}

int _15Exit_statement()
{
    int id, tok;
    s1_ptr ptr;

    if (_15loop_nest == 0) {
        RefDS(_3435);
        _6CompileErr(_3435); // "exit statement must be inside a loop"
    }

    emit_m1(61); // EXIT

    ptr = SEQ_PTR(_4Code);
    _15AppendXList(ptr->length + 1);

    /* to be back-patched */
    _15emit_forward_addr();

    tok = _15next_token();

    _15putback(tok);

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1); // tok[T_ID]
    RefDS(_688); // "exit"
    _15NotReached(id, _688);
}

int _15If_statement()
{
    int elist_base, id, prev_false, prev_false2, tok;
    int _3440;
    int _2;
    s1_ptr ptr;

    elist_base = SEQ_PTR(_15elist)->length;
    _15short_circuit = _15short_circuit + 1;
    _15short_circuit_B = 0;
    _15SC1_type = 0;
    _15Expr();
    emit_ifwhile(20); // IF

    prev_false = SEQ_PTR(_4Code)->length + 1;
    prev_false2 = 0;
    _15emit_forward_addr();

    //     if SC1_type = OR then
    if (_15SC1_type == 9) {
        // 	backpatch(SC1_patch-3, SC1_OR_IF)
        _3440 = _15SC1_patch - 3;
        _14backpatch(_3440, 149);

        _3440 = SEQ_PTR(_4Code)->length + 1;
        _14backpatch(_15SC1_patch, _3440);
    }

    if (_15SC1_type == 8) {
        _3440 = _15SC1_patch - 3;
        _14backpatch(_3440, 148);
        prev_false2 = _15SC1_patch;
    }

    _15short_circuit--;
    _15tok_match(409);
    _15Statement_list();
    tok = _15next_token();

    //     while tok[T_ID] = ELSIF do
    while (1) {
        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
        if (id != 413) // ELSIF
           break;

        emit_m1(23); // ELSE

        _3440 = SEQ_PTR(_4Code)->length + 1;
        _15AppendEList(_3440);

        _15emit_forward_addr();

        _3440 = SEQ_PTR(_4Code)->length + 1;
        _14backpatch(prev_false, _3440);

        if (prev_false2 != 0) {
            _3440 = SEQ_PTR(_4Code)->length + 1;
            _14backpatch(prev_false2, _3440);
        }

        _14StartSourceLine(1);
        _15short_circuit = _15short_circuit + 1;
        _15short_circuit_B = 0;
        _15SC1_type = 0;
        _15Expr();
        emit_ifwhile(20); // IF

        _3440 = SEQ_PTR(_4Code)->length + 1;
        prev_false = _3440;

        prev_false2 = 0;
        _15emit_forward_addr();

        if (_15SC1_type == 9) {
            // backpatch(SC1_patch-3, SC1_OR_IF)
            _3440 = _15SC1_patch - 3;
            _14backpatch(_3440, 149);

            _3440 = SEQ_PTR(_4Code)->length + 1;
            _14backpatch(_15SC1_patch, _3440);
        }
        if (_15SC1_type == 8) {
            // backpatch(SC1_patch-3, SC1_AND_IF)
            _3440 = _15SC1_patch - 3;
            _14backpatch(_3440, 148);

            prev_false2 = _15SC1_patch;
        }
        _15short_circuit--;

        _15tok_match(409); // THEN

        _15Statement_list();

        tok = _15next_token();
    }

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1);

    if (id == 23) { // ELSE
        _14StartSourceLine(0);
        emit_m1(23); // ELSE

        // AppendEList(length(Code)+1)
        _3440 = SEQ_PTR(_4Code)->length + 1;
        _15AppendEList(_3440);

        _15emit_forward_addr();

        // backpatch(prev_false, length(Code)+1)
        DeRef(_3440);
        _3440 = SEQ_PTR(_4Code)->length + 1;
        _14backpatch(prev_false, _3440);

        // if prev_false2 != 0 then
        if (prev_false2 != 0) {
            // backpatch(prev_false2, length(Code)+1)
            DeRef(_3440);
            _3440 = SEQ_PTR(_4Code)->length + 1;
            _14backpatch(prev_false2, _3440);
        }

        _15Statement_list();
    }
    else {
        _15putback(tok);

        _3440 = SEQ_PTR(_4Code)->length + 1;
        _14backpatch(prev_false, _3440);

        if (prev_false2 != 0) {
            _3440 = SEQ_PTR(_4Code)->length + 1;
            _14backpatch(prev_false2, _3440);
        }
    }

    _15tok_match(402); // END
    _15tok_match(20); // IF
    _15PatchEList(elist_base);

    DeRef(_3440);
}

int _15While_statement()
{
    int bp1, bp2, exit_base;
    int _3488;

    bp1 = SEQ_PTR(_4Code)->length + 1;
    _15short_circuit++;
    _15short_circuit_B = 0;
    _15SC1_type = 0;
    _15Expr();
    _15tok_match(410); // DO
    _14optimized_while = 0;
    emit_ifwhile(47); // WHILE
    _15short_circuit--;
    if (_14optimized_while == 0) {
        // bp2 = length(Code)+1
        bp2 = SEQ_PTR(_4Code)->length + 1;
        _15emit_forward_addr(); /* will be patched */
    }
    else {
        bp2 = 0;
    }

    _15loop_nest++;
    exit_base = SEQ_PTR(_15exit_list)->length;

    if (_15SC1_type == 9) { // OR
        // backpatch(SC1_patch-3, SC1_OR_IF)
        _14backpatch(_15SC1_patch - 3, 149);

        // backpatch(SC1_patch, length(Code)+1)
        _14backpatch(_15SC1_patch, SEQ_PTR(_4Code)->length + 1);
    }
    else {
        if(_15SC1_type == 8) {
            _3488 = _15SC1_patch - 3;
            _14backpatch(_3488, 148);
            _15AppendXList(_15SC1_patch);
        }
    }

    _15Statement_list();

    _15tok_match(402); // END
    _15tok_match(47); // WHILE
    _14StartSourceLine(1);
    emit_m1(22); // ENDWHILE
    _15loop_nest--;
    _14emit_addr(bp1);

    if (bp2 != 0) {
        _3488 = SEQ_PTR(_4Code)->length + 1;
        _14backpatch(bp2, _3488);
    }

    _15PatchXList(exit_base);
}

int _15SetPrivateScope(int s, int type_sym, int n)
{
    int hashval, scope;
    int _3514;
    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + s;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // scope = SymTab[s][S_SCOPE]
    scope = Base[S_SCOPE];

    // SC_PRIVATE or SC_LOOP_VAR
    if (find(scope, _3509)) {
        _10DefinedYet(s);
        return s;
    }

    // SC_UNDEFINED or SC_MULTIPLY_DEFINED
    if (find(scope, _3511)) {
        // SymTab[s][S_SCOPE] = SC_PRIVATE
        Base[S_SCOPE] = 3;

        // SymTab[s][S_VARNUM] = n
        Base[S_VARNUM] = n;

        // SymTab[s][S_VTYPE] = type_sym
        Base[S_VTYPE] = type_sym;

        return s;
    }

    // SC_LOCAL or SC_GLOBAL or SC_PREDEF
    if (find(scope, _3519)) {
        int t;
        /* Make an extra pointer for _10buckets */
        s1_ptr ptr0 = SEQ_PTR(_10buckets);

        // hashval = SymTab[s][S_HASHVAL]
        hashval = Base[S_HASHVAL];

        // t = buckets[hashval]
        t = *(ptr0->base + hashval);

        _3514 = Base[S_NAME]; // SymTab[s][S_NAME]
        Ref(_3514);
        Ref(_3514);
        _3514 = _10NewEntry(_3514, n, 3, -100, hashval, t, type_sym);
        Base = ptr0->base + hashval;
        *Base = _3514;
        return _3514;
    }

    RefDS(_3528);
    _6InternalErr(_3528); // "SetPS"
}

int _15For_statement()
{
    int bp1, def1, exit_base, id, loop_var;
    int loop_var_sym, tok;
    int _3553, _3555;
    s1_ptr ptr;
    object_ptr Base;

    loop_var = _15next_token();

    ptr = SEQ_PTR(loop_var);
    id = *(ptr->base + 1);
    // VARIABLE, FUNC, TYPE, PROC
    if (id != -100 && id != 501 && id != 504 && id != 27) {
        // CompileErr("a loop variable name is expected here")
        RefDS(_3534);
        _6CompileErr(_3534);
    }

    _15tok_match(3); // EQUALS
    _15Expr();
    _15tok_match(403); // TO
    _15loop_nest++;
    exit_base = SEQ_PTR(_15exit_list)->length;
    _15Expr();
    tok = _15next_token();

    ptr = SEQ_PTR(tok);
    id = *(ptr->base + 1); // tok[T_ID]
    if (id == 404) { // BY
        _15Expr();
        def1 = 0;
    }
    else {
        id = _10NewIntSym(1);
        _14emit_opnd(id);

        _15putback(tok);

        def1 = 1;
    }

    ptr = SEQ_PTR(loop_var);
    loop_var_sym = *(ptr->base + 2); // loop_var[T_SYM]

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + loop_var_sym;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    if (_4CurrentSub == _4TopLevelSub) {
        _10DefinedYet(loop_var_sym);

        // SymTab[loop_var_sym][S_SCOPE] = SC_GLOOP_VAR
        Base[S_SCOPE] = 4;

        // SymTab[loop_var_sym][S_VTYPE] = object_type
        Base[S_VTYPE] = _10object_type;
    }
    else {
        loop_var_sym = _15SetPrivateScope(loop_var_sym, _10object_type, _15param_num);

        _15param_num++;

        // SymTab[loop_var_sym][S_SCOPE] = SC_LOOP_VAR
        Base[S_SCOPE] = 2;
    }

    _14op_info1 = loop_var_sym;

    emit_for(21); // FOR
    _14emit_addr(loop_var_sym);
    _15tok_match(410); // DO
    bp1 = SEQ_PTR(_4Code)->length + 1;

    /* will be patched - don't straighten */
    _14emit_addr(0);

    if (_4OpTrace) {
        emit_m1(87); // DISPLAY_VAR
        _14emit_addr(loop_var_sym);
    }

    _15Statement_list();

    _15tok_match(402); // END
    _15tok_match(21); // FOR
    _14StartSourceLine(1); // TRUE
    _14op_info1 = loop_var_sym;
    _14op_info2 = bp1 + 1;

    if (def1) {
        emit_endfor(54); // ENDFOR_INT_UP1 /* loop var might not be integer */
    }
    else {
        emit_endfor(39); // ENDFOR_GENERAL /* will be set at runtime by FOR op */
    }

    _14backpatch(bp1, SEQ_PTR(_4Code)->length + 1);
    _15PatchXList(exit_base);
    _15loop_nest--;

    if (_4OpTrace) {
        emit_m1(90); // ERASE_SYMBOL
        _14emit_addr(loop_var_sym);
    }

    _10Hide(loop_var_sym);

    DeRef(_3555);
    DeRef(_3553);
}

int _15Global_declaration(int type_ptr, int is_global)
{
    int h, id, sym, tok;
    int _3579 = 0, _3581 = 0;
    object_ptr Base, Base3;
    s1_ptr ptr, ptr2, ptr3;

    ptr2 = SEQ_PTR(_10buckets);

    while (1) {
        tok = _15next_token();

        ptr = SEQ_PTR(tok);
        Base = ptr->base;

        id = *(Base + 1); // tok[T_ID]

        // VARIABLE or FUNC or TYPE or PROC
        if (id != -100 && id != 501 && id != 504 && id != 27) {
            RefDS(_3584); // "a name is expected here"
            _6CompileErr(_3584);
        }

        sym = *(Base + 2); // tok[T_SYM]

        _10DefinedYet(sym);

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + sym;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        // 	if find(SymTab[sym][S_SCOPE], {SC_GLOBAL, SC_PREDEF}) then
        _3581 = find(Base[S_SCOPE], _2127);
        if (_3581) {
            h = Base[S_HASHVAL]; // [sym][S_HASHVAL]

            // sym = NewEntry(SymTab[sym][S_NAME], 0, 0, VARIABLE, h, buckets[h], 0)
            _3581 = Base[S_NAME];
            Ref(_3581);
            DeRef(_3579);
            _3579 = *(ptr2->base + h);
            Ref(_3579);
            Ref(_3581);
            Ref(_3579);
            sym = _10NewEntry(_3581, 0, 0, -100, h, _3579, 0);

            // buckets[h] = sym
            Base3 = ptr2->base + h; // buckets[h]
            *Base3 = sym;

            /* Redo ptr and Base for the new SymTab entry. */
            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + sym;
            ptr = SEQ_PTR(*Base);
            Base = ptr->base;
        }

        if (is_global) {
            // SymTab[sym][S_SCOPE] = SC_GLOBAL
            Base[S_SCOPE] = 6;
        }
        else {
            // SymTab[sym][S_SCOPE] = SC_LOCAL
            Base[S_SCOPE] = 5;
        }

        if (type_ptr == 0) {
            // SymTab[sym][S_MODE] = M_CONSTANT
            *(Base + 3) = 2;

            Base3 = ptr2->base + Base[S_HASHVAL]; // buckets[SymTab[sym][S_HASHVAL]]
            *Base3 = Base[S_SAMEHASH]; // SymTab[sym][S_SAMEHASH]

            _15tok_match(3); // EQUALS
            _14StartSourceLine(0); // FALSE
            _14emit_opnd(sym);

            /* no new symbols can be defined in here */
            _15Expr();

            Base3 = ptr2->base + Base[S_HASHVAL]; // buckets[SymTab[sym][S_HASHVAL]]
            *Base3 = sym;

            // SymTab[sym][S_USAGE] = U_WRITTEN
            Base[S_USAGE] = 2;
            emit_assign();
        }
        else {
            // 	    SymTab[sym][S_MODE] = M_NORMAL
            Base[S_MODE] = 1;

            ptr3 = SEQ_PTR(_4SymTab);
            Base3 = ptr3->base + type_ptr;
            ptr3 = SEQ_PTR(*Base3);
            Base3 = ptr3->base + 9; // SymTab[type_ptr][S_TOKEN]
            if (*Base3 == 414) { // OBJECT
                // SymTab[sym][S_VTYPE] = object_type
                Base[S_VTYPE] = _10object_type;
            }
            else {
                // SymTab[sym][S_VTYPE] = type_ptr
                Base[S_VTYPE] = type_ptr;
            }
        }
        tok = _15next_token();

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
        if (id != -30) // COMMA
            break;
    }

    _15putback(tok);

    DeRef(_3581);
    DeRef(_3579);
}

int _15Private_declaration(int type_sym)
{
    int id, sym, tok;
    s1_ptr ptr;

    while (1) {
        tok = _15next_token();

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
        // VARIABLE, FUNC, TYPE, PROC, NAMESPACE
        if (id != -100 && id != 501 && id != 504 && id != 27 && id != 523) {
            RefDS(_3634);
            _6CompileErr(_3634); // "a variable name is expected here"
        }

        // 	sym = SetPrivateScope(tok[T_SYM], type_sym, param_num)
        sym = *(ptr->base + 2);
        sym = _15SetPrivateScope(sym, type_sym, _15param_num);

        _15param_num++;

        tok = _15next_token();

        // 	if tok[T_ID] != COMMA then
        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);
        if (id != -30)
            break;
    }

    _15putback(tok);
}

int _15Procedure_call(int tok)
{
    int id, s, scope, temp_tok;
    object_ptr Base;
    s1_ptr ptr;

    _15tok_match(-26); // LEFT_ROUND

    ptr = SEQ_PTR(tok);
    s = *(ptr->base + 2); // [T_SYM]

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + s;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    scope = Base[S_SCOPE]; // SymTab[s][S_SCOPE]

    _15ParseArgs(s);

    /* Is this a predefined routine? */
    if (scope == 7) { // SC_PREDEF
        int opcode;

        opcode = Base[S_OPCODE]; // SymTab[s][S_OPCODE]
        _14emit_op(opcode);

        if (opcode == 126) { // ABORT
            temp_tok = _15next_token();

            _15putback(temp_tok);

            // NotReached(temp_tok[T_ID], "abort()")
            ptr = SEQ_PTR(temp_tok);
            id = *(ptr->base + 1);
            _15NotReached(id, _3664);
        }
    }
    else {
        _14op_info1 = s;
        emit_proc();
        if (_4OpTrace)
            emit_m1(89); // UPDATE_GLOBALS
    }
}

int _15Print_statement()
{
    _14emit_opnd(_10NewIntSym(1));
    _15Expr();
    emit_m2(36); // QPRINT
}

int _15Statement_list()
{
    int id, tok;
    s1_ptr ptr;

    _15stmt_nest++;

    while (1) {
        tok = _15next_token();

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1); // tok[T_ID]

        /* VARIABLE or QUALIFIED_VARIABLE */
        if (id == -100 || id == 515) {
            _14StartSourceLine(1); // TRUE
            _15Assignment(tok);
            continue;
        }
        /* PROC or QUALIFIED PROC */
        if (id == 27 || id == 525) {
            _14StartSourceLine(1); // TRUE
            _15Procedure_call(tok);
            continue;
        }
        /* IF */
        if (id == 20) {
            _14StartSourceLine(1); // TRUE
            _15If_statement();
            continue;
        }
        /* FOR */
        if (id == 21) {
            _14StartSourceLine(1); // TRUE
            _15For_statement();
            continue;
        }
        /* WHILE */
        if (id == 47) {
            _14StartSourceLine(1); // TRUE
            _15While_statement();
            continue;
        }
        /* RETURN */
        if (id == 412) {
            _14StartSourceLine(1); // TRUE
            _15Return_statement();
            continue;
        }
        /* EXIT */
        if (id == 61) {
            _14StartSourceLine(1); // TRUE
            _15Exit_statement();
            continue;
        }
        /* ? */
        if (id == -31) {
            _14StartSourceLine(1); // TRUE
            _15Print_statement();
            continue;
        }

        _15putback(tok);

        _15stmt_nest--;
        _15InitDelete();

        break;
    }
}

int _15SubProg(int prog_type, int is_global)
{
    int h, i, id, p, prog_name;
    int pt, sym, sym0, tok;
    int _3692 = 0;
    int _1, _2;
    object_ptr Base, Base00;
    s1_ptr ptr, ptr0, ptr00;

    ptr0 = SEQ_PTR(_10buckets);

    _15LeaveTopLevel();
    prog_name = _15next_token();

    ptr = SEQ_PTR(prog_name);
    id = *(ptr->base + 1); // prog_name[T_ID]

    /* VARIABLE or FUNC or TYPE or PROC */
    if (id != -100 && id != 501 && id != 504 && id != 27) {
        RefDS(_3584);
        _6CompileErr(_3584); // "a name is expected here"
    }

    p = *(ptr->base + 2); // prog_name[T_SYM]

    _10DefinedYet(p);

    if (prog_type == 405) { // PROCEDURE
        pt = 27; // PROC
    }
    else {
        if (prog_type == 406) {// FUNCTION
            pt = 501; // FUNC
        }
        else {
            pt = 504; // TYPE
        }
    }

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + p;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    _3692 = Base[S_MODE];
    if (find(_3692, _3700)) { // SC_PREDEF or SC_GLOBAL
        if (_3692 == 7) { // SC_PREDEF
            /* built-in routine %s redefined. */
            err_add(NewString("built-in routine "));
            err_add(Base[S_NAME]);
            err_add(NewString(" redefined."));

            /* Give the stack to Warning. */
            _6Warning(error_stack);

            /* Manually reset the stack. */
            RefDS(_39);
            error_stack = _39;
        }

        h = Base[S_HASHVAL]; // SymTab[p][S_HASHVAL]
        sym = *(ptr0->base + h); // buckets[h]

        _3692 = Base[S_NAME]; // SymTab[p][S_NAME]
        Ref(_3692);
        Ref(_3692);
        p = _10NewEntry(_3692, 0, 0, pt, h, sym, 0);
        Base00 = ptr0->base + h; // buckets[h]
        *(Base00) = p;

        /* p has been redefined so, redo Base */
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + p;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;
    }

    _4CurrentSub = p;
    _10temps_allocated = 0;

    if (is_global) {
        // SymTab[p][S_SCOPE] = SC_GLOBAL
        Base[S_SCOPE] = 6;
    }
    else {
        // SymTab[p][S_SCOPE] = SC_LOCAL
        Base[S_SCOPE] = 5;
    }

    // SymTab[p][S_TOKEN] = pt
    Base[S_TOKEN] = pt;

    //     if length(SymTab[p]) < SIZEOF_ROUTINE_ENTRY then
    ptr00 = SEQ_PTR(_4SymTab);
    Base00 = ptr00->base + p;
    ptr00 = SEQ_PTR(*Base00);

    int len;
    len = ptr00->length;

    if (len < FIELD_MAX) { // SIZEOF_ROUTINE_ENTRY
        // 	SymTab[p] = SymTab[p] & repeat(0, SIZEOF_ROUTINE_ENTRY -
        _3692 = Repeat (0, FIELD_MAX - len);
        Concat((object_ptr)&_3692, *Base00, (s1_ptr)_3692);
        *Base00 = _3692;

        /* SymTab[p] has been expanded so, we have to redo Base */
        /* Otherwise, Base goes by the old length */
        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + p;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;
    }

    // SymTab[p][S_CODE] = 0
    Base[S_CODE] = 0;

    // SymTab[p][S_FIRSTLINE] = gline_number
    Base[S_FIRSTLINE] = _4gline_number;

    // SymTab[p][S_TEMPS] = 0
    Base[S_TEMPS] = 0;

    _14StartSourceLine(0); // FALSE
    _15tok_match(-26); // LEFT_ROUND
    tok = _15next_token();
    _15param_num = 0;

    while (1) {
        ptr00 = SEQ_PTR(tok);
        id = *(ptr00->base + 1); // tok[T_ID]
        if (id == -27) // RIGHT_ROUND
            break;

        if (id != 504 && id != 526) { // TYPE and QUALIFIED_TYPE
            if (id == -100 || id == 515) { // VARIABLE and QUALIFIED_VARIABLE
                // UndefinedVar(tok[T_SYM])
                sym0 = *(ptr00->base + 2);
                _15UndefinedVar(sym0);
            }
            RefDS(_3761);
            _6CompileErr(_3761); /* "a type is expected here" */
        }

        sym0 = *(ptr00->base + 2);

        tok = _15next_token();

        // 	if not find(tok[T_ID], {VARIABLE, FUNC, TYPE, PROC, NAMESPACE}) then
        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);

        if (id != -100 && id != 501 && id != 504 && id != 27 && id != 523) {
            RefDS(_3768);
            _6CompileErr(_3768); // "a parameter name is expected here"
        }

        sym = _15SetPrivateScope(*(ptr->base + 2), sym0, _15param_num);

        _15param_num++;

        ptr = SEQ_PTR(_4SymTab);
        Base = ptr->base + sym;
        ptr = SEQ_PTR(*Base);
        Base = ptr->base;

        // SymTab[sym][S_USAGE] = U_WRITTEN
        Base[S_USAGE] = 2;

        tok = _15next_token();

        ptr00 = SEQ_PTR(tok);
        id = *(ptr00->base + 1); // tok[T_ID]
        if (id == -30) { // COMMA
            tok = _15next_token();

            ptr00 = SEQ_PTR(tok);
            id = *(ptr00->base + 1); // tok[T_ID]
            if (id == -27) { // RIGHT_ROUND
                RefDS(_3783);
                _6CompileErr(_3783); // "expected to see a parameter declaration, not ')'"
            }
        }
        else {
            if (id != -27) { // RIGHT_ROUND
                RefDS(_3786);
                _6CompileErr(_3786); // "badly-formed list of parameters - expected ',' or ')'"
            }
        }
    }

    /* Base seems to lose it's effect here so, we have to create it again */
    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + p;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[p][S_NUM_ARGS] = param_num
    Base[S_NUM_ARGS] = _15param_num;

    _3692 = Base[S_TOKEN]; // SymTab[p][S_TOKEN]
    if (_3692 == 504 && _15param_num != 1) {
        RefDS(_3796);
        _6CompileErr(_3796); // "types must have exactly one parameter"
    }

    tok = _15next_token();

    ptr00 = SEQ_PTR(tok);
    id = *(ptr00->base + 1); // tok[T_ID]
    if (id == 504 || id == 526) { // TYPE or QUALIFIED_TYPE
        while (1) {

        // 	Private_declaration(tok[T_SYM])
        sym0 = *(ptr00->base + 2);
        _15Private_declaration(sym0);

        tok = _15next_token();

        ptr00 = SEQ_PTR(tok);
        id = *(ptr00->base + 1);
        if (id != 504 && id != 526)
            break;
        }
    }

    sym = Base[S_NEXT]; // SymTab[p][S_NEXT]

    _3692 = Base[S_NUM_ARGS]; // SymTab[p][S_NUM_ARGS]

    /* Type check all the arguments */
    for (i = 1;i <= _3692;i++) {
        _15TypeCheck(sym);

        // sym = SymTab[sym][S_NEXT]
        ptr00 = SEQ_PTR(_4SymTab);
        Base00 = ptr00->base + sym;
        ptr00 = SEQ_PTR(*Base00);
        sym = *(ptr00->base + S_NEXT);
    }

    if (_4OpTrace) {
        emit_m1(88); // ERASE_PRIVATE_NAMES
        _14emit_addr(p);

        // sym = SymTab[p][S_NEXT]
        sym = Base[S_NEXT];

        _3692 = Base[S_NUM_ARGS]; // SymTab[p][S_NUM_ARGS]
        for (i = 1;i < _3692;i++) {
            emit_m1(87); // DISPLAY_VAR
            _14emit_addr(sym);

            // sym = SymTab[sym][S_NEXT]
            ptr = SEQ_PTR(_4SymTab);
            Base = ptr->base + sym;
            ptr = SEQ_PTR(*Base);
            sym = *(ptr->base + 2);
        }

        emit_m1(89); // UPDATE_GLOBALS
    }

    _15putback(tok);

    _15FuncReturn = 0; // FALSE
    _15Statement_list();
    _15tok_match(402); // END
    _10ExitScope();
    _15tok_match(prog_type);

    if (prog_type != 405) { // PROCEDURE
        if (_15FuncReturn == 0) {
            if (prog_type == 406) { // FUNCTION
                RefDS(_3821);
                _6CompileErr(_3821); // "no value returned from function"
            }
            else {
                RefDS(_3822);
                _6CompileErr(_3822); // "type must return true / false value"
            }
        }
        /* Function / Type shouldn't reach here */
        emit_m1(43); // BADRETURNF
    }
    else {
        _14StartSourceLine(1); // TRUE

        if (_4OpTrace) {
            emit_m1(88); // ERASE_PRIVATE_NAMES
            _14emit_addr(p);
        }
        emit_returnp();
    }

    /* Base appears to lose it's effect again so, redo it. */
    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + p;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[p][S_STACK_SPACE] = temps_allocated + param_num
    Base[S_STACK_SPACE] = _10temps_allocated + _15param_num;

    _15StraightenBranches();
    _15EnterTopLevel();

    DeRef(prog_name);
    DeRef(_3692);
}

int _15InitGlobals()
{
    _11ResetTP();
    _4OpTypeCheck = 1;
    _4OpWarning = 1;
}

int Comp(int a, int b)
/* Compare things in SetWith. */
{
    return compare(a, b) == 0;
}

int _15SetWith(int on_off)
{
    int option, tok;
    int _3833, _2;

    option = _11StringToken();

    /* WARNING */
    if (Comp(option, _3861)) {
        _4OpWarning = on_off;
        goto END;
    }

    /* TRACE */
    if (Comp(option, _756)) {
        _4OpTrace = on_off;
        goto END;
    }

    /* TYPE CHECK */
    if (Comp(option, _3834)) {
        _4OpTypeCheck = on_off;
        goto END;
    }

    /* PROFILE */
    if (Comp(option, _826)) {
        if (on_off) {
            if(_11AnyTimeProfile) {
                RefDS(_15mix_msg);
                _6Warning(_15mix_msg);
                _4OpProfileStatement = 0;
            }
            else {
                _11AnyStatementProfile = 1;
                _4OpProfileStatement = on_off;
            }
        }
        goto END;
    }

    /* PROFILE TIME */
    if (Comp(option, _3840)) {
        _4OpProfileTime = on_off;
        if (_4OpProfileTime) {
            if (_11AnyStatementProfile) {
                RefDS(_15mix_msg);
                _6Warning(_15mix_msg);
                _4OpProfileTime = 0;
            }
            tok = _15next_token();

            object_ptr Base;
            s1_ptr ptr;

            ptr = SEQ_PTR(tok);
            Base = ptr->base + 1; // tok[T_ID]

            if (*Base == 502) { // ATOM
                Base++; // tok[T_SYM]
                ptr = SEQ_PTR(_4SymTab);
                Base = ptr->base + *Base;
                ptr = SEQ_PTR(*Base);
                Base = ptr->base + 1; // SymTab[tok[T_SYM]][S_OBJ]
                if (IS_ATOM_INT(*Base))
                    _15sample_size = *Base;
                else
                    _15sample_size = -1;

                if (_15sample_size < 1 && _4OpProfileTime) {
                    RefDS(_3858);
                    _6CompileErr(_3858);
                }
            }
            else {
                _15putback(tok);
                _15sample_size = 25000;
            }
            if (_4OpProfileTime) {
                if (_4EDOS) {
                    _11AnyTimeProfile = 1;
                }
            }
        }
        goto END;
    }

    RefDS(_3869);
    _6CompileErr(_3869); /* unknown with/without option */

END:
    DeRefi(option);
}

int _15ExecCommand()
{
    _15StraightenBranches();
}

int _15parser()
{
    int tok, id;
    int _3870, _3876;
    object_ptr Base;
    s1_ptr ptr;

    while(1) {
        tok = _15next_token();

        ptr = SEQ_PTR(tok);
        id = *(ptr->base + 1);

        /* VARIABLE OR QUALIFIED VARIABLE */
        if (id == -100 || id == 515 ) {
            _14StartSourceLine(1);
            _15Assignment(tok);
            _15ExecCommand();
            continue;
        }

        /* PROCEDURE, FUNCTION, OR TYPE DECLARE */
        if (id ==  405 || id == 406 || id == 415 ) {
            _15SubProg(id, 0);
            continue;
        }

        /* PROCEDURE */
        if (id == 27 || id == 525) {
            _14StartSourceLine(1);
            _15Procedure_call(tok);
            _15ExecCommand();
            continue;
        }

        /* GLOBAL */
        if (id == 411) {
            tok = _15next_token();

            ptr = SEQ_PTR(tok);
            id = *(ptr->base + 1);

            /* PROCEDURE, FUNCTION, OR TYPE DECLARE */
            if (id == 405 || id == 406 || id == 415) {
                _15SubProg(id, 1);
                continue;
            }

            /* CONSTANT */
            if (id == 416) {
                _15Global_declaration(0, 1);
                _15ExecCommand();
               continue;
            }

            /* TYPE (Will be removed) */
            if (id == 504) {
                _3876 = *(ptr->base + 2);
                _15Global_declaration(_3876, 1);
                continue;
            }

            /* VARIABLE OR QUALIFIED VARIABLE (ERROR)*/
            if (id == -100 || id == 515 ) {
                // UndefinedVar(tok[T_SYM])
                _3870 = *(ptr->base + 2);
                _15UndefinedVar(_3870);
            }

            RefDS(_3898);
            _6CompileErr(_3898);
            continue;
        }

        /* CONSTANT */
        if (id == 416) {
            _15Global_declaration(0, 0);
            continue;
        }

        /* IF */
        if (id == 20) {
            _14StartSourceLine(1);
            _15If_statement();
            _15ExecCommand();
            continue;
        }

        /* FOR */
        if (id == 21) {
            _14StartSourceLine(1);
            _15For_statement();
            _15ExecCommand();
            continue;
        }

        /* WHILE */
        if (id == 47) {
            _14StartSourceLine(1);
            _15While_statement();
            _15ExecCommand();
            continue;
        }

        /* INCLUDE */
        if (id == 417) {
            _11IncludeScan();
            continue;
        }

        /* END OF FILE */
        if (id == -21) {
            if (_11IncludePop()) {
                _11read_line();
                continue;
            }
            else {
                break;
            }
        }

        /* WITHOUT */
        if (id == 420) {
            _15SetWith(0);
            continue;
        }

        /* WITH */
        if (id == 419) {
            _15SetWith(1);
            continue;
        }

        /* TYPE (Will be removed) */
        if (id == 504 || id == 526) {
            _3876 = *(ptr->base + 2);
            _15Global_declaration(_3876, 0);
            continue;
        }

        /* QUESTION MARK (Will be removed) */
        if (id == -31) {
            _14StartSourceLine(1);
            _15Print_statement();
            _15ExecCommand();
            continue;
        }

        /* ALL BELOW WILL FAIL. DO NOT MOVE FAILS ABOVE THIS LINE. */
        /* FUNC OR QUALIFIED_FUNC */
        if (id == 501 || id == 524 ) {
            //     CompileErr("function result must be assigned or used")
            RefDS(_3913);
            _6CompileErr(_3913);
            continue;
        }

        /* RETURN */
        if (id == 412) {
            _15Return_statement();
            continue;
        }

        /* EXIT */
        if (id == 61) {
            RefDS(_3916);
            _6CompileErr(_3916);
            continue;
        }

        /* ILLEGAL CHARACTER */
        if (id == -20) {
            RefDS(_3924);
            _6CompileErr(_3924);
            continue;
        }

        /* UNKNOWN */
        RefDS(_3925);
        _6CompileErr(_3925);
    }

    emit_m1(34); // RETURNT
    _15StraightenBranches();

    ptr = SEQ_PTR(_4SymTab);
    Base = ptr->base + _4TopLevelSub;
    ptr = SEQ_PTR(*Base);
    Base = ptr->base;

    // SymTab[TopLevelSub][S_CODE] = Code
    RefDS(_4Code);
    Base[S_CODE] = _4Code;
}

